package com.lb.pdm.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lb.pdm.common.constants.RedisConstants;
import com.lb.pdm.common.result.GraceJSONResult;
import com.lb.pdm.entity.*;
import com.lb.pdm.entity.bo.HouseholdQueryBO;
import com.lb.pdm.entity.vo.HouseholdMemberVO;
import com.lb.pdm.mapper.*;
import com.lb.pdm.service.HouseholdMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 户籍成员表 服务实现类
 * </p>
 *
 * @author pdm
 * @since 2025-10-29
 */
@Service
public class HouseholdMemberServiceImpl extends ServiceImpl<HouseholdMemberMapper, HouseholdMember> implements HouseholdMemberService {
    @Autowired
    private HouseholdMemberMapper householdMemberMapper;
    @Autowired
    private PersonInfoMapper personInfoMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private HouseholdInfoMapper householdInfoMapper;
    @Autowired
    private CertificateApplicationMapper certificateApplicationMapper;
    @Autowired
    private CertificateInfoMapper certificateInfoMapper;

    @Override
    public List<HouseholdMemberVO> listHouseholds(HouseholdQueryBO queryBO) {
        int start = (queryBO.getPageNum() - 1) * queryBO.getPageSize();
        return householdMemberMapper.listHouseholdsWithConditions(
                queryBO.getName(),
                queryBO.getIdCard(),
                queryBO.getAddress(),
                start,
                queryBO.getPageSize()
        );
    }

    @Override
    @Transactional
    public GraceJSONResult deathCancellation(String idCard, String token) {
        LambdaQueryWrapper<PersonInfo> personInfoQuery = new LambdaQueryWrapper<>();
        personInfoQuery.eq(PersonInfo::getIdCard, idCard);
        PersonInfo personInfo = personInfoMapper.selectOne(personInfoQuery);

        if (personInfo == null) {
            return GraceJSONResult.errorMsg("该人员不存在");
        }

        personInfo.setStatus((byte)0);

        String sysUserString = redisTemplate.opsForValue().get(RedisConstants.USER_TOKEN_PREFIX + token);
        SysUser sysUser = JSON.parseObject(sysUserString, SysUser.class);

        personInfo.setUpdateBy(sysUser.getId());
        personInfo.setUpdateTime(new Date());

        int personUpdateRes = personInfoMapper.updateById(personInfo);
        if (personUpdateRes <= 0) {
            return GraceJSONResult.errorMsg("更新人员信息失败");
        }

        Long personInfoId = personInfo.getId();

        LambdaQueryWrapper<HouseholdMember> householdMemberQuery = new LambdaQueryWrapper<>();
        householdMemberQuery.eq(HouseholdMember::getPersonId, personInfoId);
        HouseholdMember householdMember = householdMemberMapper.selectOne(householdMemberQuery);

        householdMember.setStatus((byte)0);
        householdMember.setLeaveDate(new Date());
        householdMember.setLeaveReason("死亡");
        householdMember.setUpdateBy(sysUser.getId());
        householdMember.setUpdateTime(new Date());

        int householdMemberUpdateRes = householdMemberMapper.updateById(householdMember);
        if (householdMemberUpdateRes <= 0) {
            return GraceJSONResult.errorMsg("更新户籍成员信息失败");
        }

        Long householdId = householdMember.getHouseholdId();
        LambdaQueryWrapper<HouseholdInfo> householdInfoQuery = new LambdaQueryWrapper<>();
        householdInfoQuery.eq(HouseholdInfo::getId, householdId);
        HouseholdInfo householdInfo = householdInfoMapper.selectOne(householdInfoQuery);

        // 死者是户主
        if (householdInfo.getHouseholderId().equals(personInfoId)) {
            // 查询该户籍下所有活着的成员（不包括刚刚设置为死亡状态的成员）
            LambdaQueryWrapper<HouseholdMember> householdMemberQuery2 = new LambdaQueryWrapper<>();
            householdMemberQuery2.eq(HouseholdMember::getHouseholdId, householdId)
                    .eq(HouseholdMember::getStatus, 1);
            List<HouseholdMember> householdMembers = householdMemberMapper.selectList(householdMemberQuery2);

            if (householdMembers.isEmpty()) { // 户籍中除了死者无其他成员
                householdInfo.setStatus((byte)0);

            } else { // 户籍中还有其他成员
                // 重新选户主（不需要传excludePersonId，因为死者已经不在列表中了）
                Long newHouseholderId = selectNewHouseholder(householdMembers, null);

                if (newHouseholderId == null) {
                    return GraceJSONResult.errorMsg("无法选择合适的新户主，请人工处理");
                }

                // 更新户籍信息，指定新户主
                householdInfo.setHouseholderId(newHouseholderId);
            }

            householdInfo.setUpdateBy(sysUser.getId());
            householdInfo.setUpdateTime(new Date());
            int householdInfoUpdateRes = householdInfoMapper.updateById(householdInfo);
            if (householdInfoUpdateRes <= 0) {
                return GraceJSONResult.errorMsg("更新户籍信息失败");
            }
        }

        //更新证件信息
        LambdaQueryWrapper<CertificateInfo> certificateInfoQuery = new LambdaQueryWrapper<>();
        certificateInfoQuery.eq(CertificateInfo::getPersonId, personInfoId);
        CertificateInfo certificateInfo = certificateInfoMapper.selectOne(certificateInfoQuery);
        if (certificateInfo != null) {
            certificateInfo.setStatus((byte)0);
            certificateInfo.setUpdateBy(sysUser.getId());
            certificateInfo.setUpdateTime(new Date());
            int certificateInfoUpdateRes = certificateInfoMapper.updateById(certificateInfo);
            if (certificateInfoUpdateRes <= 0) {
                return GraceJSONResult.errorMsg("更新证件信息失败");
            }
        }


        LambdaQueryWrapper<CertificateApplication> certificateApplicationQuery = new LambdaQueryWrapper<>();
        certificateApplicationQuery.eq(CertificateApplication::getPersonId, personInfoId);
        CertificateApplication application = certificateApplicationMapper.selectOne(certificateApplicationQuery);
        if (application != null) {
            application.setApplicationStatus((byte)3);
            application.setUpdateBy(sysUser.getId());
            application.setUpdateTime(new Date());
            int updateRes = certificateApplicationMapper.updateById(application);
            if (updateRes <= 0) {
                return GraceJSONResult.errorMsg("更新申请信息失败");
            }
        }

        return GraceJSONResult.ok();
    }

    /**
     * 选择新户主
     * 选择规则：
     * 1. 优先选择成年人（年龄≥18岁）
     * 2. 在成年人中选择年龄最大的
     * 3. 如果都是未成年人，选择年龄最大的未成年人
     * 4. 如果年龄相同，按加入户籍时间优先（joinDate最早的）
     *
     * @param householdMembers 户籍成员列表
     * @param excludePersonId 需要排除的人员ID（即将迁出的户主）
     * @return 新户主的人员ID，如果无法选择则返回null
     */
    private Long selectNewHouseholder(List<HouseholdMember> householdMembers, Long excludePersonId) {
        // 过滤掉需要排除的人员（如果有的话），只保留在册成员
        List<HouseholdMember> availableMembers = householdMembers.stream()
                .filter(member -> excludePersonId == null || !Objects.equals(member.getPersonId(), excludePersonId))
                .filter(member -> member.getStatus() == 1) // 只考虑在册成员
                .collect(Collectors.toList());

        if (availableMembers.isEmpty()) {
            return null;
        }

        // 获取所有候选成员的详细信息
        List<Long> personIds = availableMembers.stream()
                .map(HouseholdMember::getPersonId)
                .collect(Collectors.toList());

        LambdaQueryWrapper<PersonInfo> personQuery = new LambdaQueryWrapper<>();
        personQuery.in(PersonInfo::getId, personIds)
                .eq(PersonInfo::getStatus, 1); // 只查询正常状态的人员
        List<PersonInfo> persons = personInfoMapper.selectList(personQuery);

        if (persons.isEmpty()) {
            return null;
        }

        // 创建候选人信息列表，包含成员信息和个人信息
        List<HouseholderCandidate> candidates = new ArrayList<>();
        for (HouseholdMember member : availableMembers) {
            PersonInfo person = persons.stream()
                    .filter(p -> Objects.equals(p.getId(), member.getPersonId()))
                    .findFirst()
                    .orElse(null);

            if (person != null && person.getBirthDate() != null) {
                int age = calculateAge(person.getBirthDate());
                candidates.add(new HouseholderCandidate(member, person, age));
            }
        }

        if (candidates.isEmpty()) {
            return null;
        }

        // 按照选择规则排序
        candidates.sort((c1, c2) -> {
            // 1. 优先选择成年人
            boolean c1IsAdult = c1.age >= 18;
            boolean c2IsAdult = c2.age >= 18;

            if (c1IsAdult && !c2IsAdult) {
                return -1; // c1优先
            }
            if (!c1IsAdult && c2IsAdult) {
                return 1; // c2优先
            }

            // 2. 年龄大的优先
            if (c1.age != c2.age) {
                return Integer.compare(c2.age, c1.age); // 降序，年龄大的在前
            }

            // 3. 年龄相同时，按加入户籍时间优先（joinDate最早的）
            Date joinDate1 = c1.member.getJoinDate();
            Date joinDate2 = c2.member.getJoinDate();

            if (joinDate1 != null && joinDate2 != null) {
                return joinDate1.compareTo(joinDate2); // 升序，时间早的在前
            }

            // 4. 如果加入时间也相同或为空，按人员ID排序（保证结果的确定性）
            return Long.compare(c1.person.getId(), c2.person.getId());
        });

        // 返回排序后的第一个候选人
        HouseholderCandidate selectedCandidate = candidates.get(0);

        // 记录选择结果（可以用于日志或审计）
        String selectionReason = buildSelectionReason(selectedCandidate, candidates);
        System.out.println("选择新户主: " + selectedCandidate.person.getName() +
                " (ID: " + selectedCandidate.person.getId() + "), 原因: " + selectionReason);

        return selectedCandidate.person.getId();
    }

    /**
     * 计算年龄
     * @param birthDate 出生日期
     * @return 年龄
     */
    private int calculateAge(Date birthDate) {
        if (birthDate == null) {
            return 0;
        }

        Calendar birth = Calendar.getInstance();
        birth.setTime(birthDate);

        Calendar now = Calendar.getInstance();

        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);

        // 检查是否还没到生日
        if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }

        return Math.max(0, age); // 确保年龄不为负数
    }

    /**
     * 构建选择原因说明
     * @param selected 被选中的候选人
     * @param allCandidates 所有候选人
     * @return 选择原因
     */
    private String buildSelectionReason(HouseholderCandidate selected, List<HouseholderCandidate> allCandidates) {
        StringBuilder reason = new StringBuilder();

        boolean hasAdults = allCandidates.stream().anyMatch(c -> c.age >= 18);
        boolean selectedIsAdult = selected.age >= 18;

        if (hasAdults && selectedIsAdult) {
            reason.append("成年人优先");
        } else if (!hasAdults) {
            reason.append("所有成员均为未成年人");
        }

        long sameAgeCount = allCandidates.stream()
                .filter(c -> c.age == selected.age)
                .filter(c -> selectedIsAdult == (c.age >= 18)) // 同样是成年人或未成年人
                .count();

        if (sameAgeCount > 1) {
            reason.append(", 同龄者中按加入时间优先");
        } else {
            reason.append(", 年龄最大(").append(selected.age).append("岁)");
        }

        return reason.toString();
    }
}
